package cn.uc.grapics;

import java.util.ArrayList;
import java.util.List;

import cn.uc.app.R.id;
import cn.uc.util.GraphicsUtil;

import android.R.integer;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.MotionEvent;

public abstract class GraphicsItem {
    protected Rect boundingRect = new Rect();
    protected Paint mPaint = new Paint();
    private float angle = 0;
    private int zorder = 1;
    private int transeparent;
    private boolean isVisible = true;
    private boolean isFocus = false;
    private boolean isTouchable = true;
    private boolean isFocusable = true;
    private PointF scaleRatio = new PointF(1, 1);
    
    protected GraphicsItem parent = null;
    protected List<GraphicsItem> children = new ArrayList<GraphicsItem>();
    
    public GraphicsItem() {
        // XXX Auto-generated constructor stub
    }
    
    public Rect boundingRect() {
        return boundingRect;
    }
    
    public void setBoundingRect(Rect boundingRect) {
        this.boundingRect = boundingRect;
    }
    
    public void setPos(int ax, int ay){
        boundingRect.set(ax, ay, ax + boundingRect.width(), ay + boundingRect.height());
    }
    
    public int getX(){
        return boundingRect.left;
    }
    
    public int getY(){
        return boundingRect.top;
    }
    
    public int getWidth(){
        return boundingRect.width();
    }
    
    public int getHeight(){
        return boundingRect.height();
    }
    
    public int getBottom(){
        return boundingRect.bottom;
    }
    
    public int getRight(){
        return boundingRect.right;
    }
    
    
    public float getAngle() {
        return angle;
    }
    public void setAngle(float angle) {
        this.angle = angle;
    }
    
    public PointF getScaleRatio() {
        return scaleRatio;
    }

    public void setScaleRatio(PointF scaleRatio) {
        this.scaleRatio = scaleRatio;
    }
    
    public void setScaleRatio(float xRatio, float yRatio) {
        this.scaleRatio.x = xRatio;
        this.scaleRatio.y = yRatio;
    }

    public int getZorder() {
        return zorder;
    }
    public void setZorder(int zorder) {
        this.zorder = zorder;
    }
    public int getTranseparent() {
        return transeparent;
    }
    public void setTranseparent(int transeparent) {
        this.transeparent = transeparent;
    }
    public boolean isVisible() {
        return isVisible;
    }
    public void setVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }
    
    public boolean isFocus() {
        return isFocus;
    }

    public void setFocus(boolean isFocus) {
        this.isFocus = isFocus;
    }

    public boolean isTouchable() {
        return isTouchable;
    }
    
    public void setTouchable(boolean isTouchable) {
        this.isTouchable = isTouchable;
    }
       
    
    public boolean isFocusable() {
        return isFocusable;
    }

    public void setFocusable(boolean isFocusable) {
        this.isFocusable = isFocusable;
    }

    public void addChild(GraphicsItem aItem){
        children.add(aItem);
        aItem.setParent(this);
    }
    
    public void setParent(GraphicsItem aParent){
        parent = aParent;
    }
    
    public GraphicsItem getParent(){
        return parent;
    }
    
    public Rect mapToParent(Rect aRect){
        Rect sRect = aRect;
        if(parent != null){
            sRect = new Rect(parent.getX() + aRect.left, parent.getY() + aRect.top, aRect.width(), aRect.height());
        }
        
        return sRect;
    }
    
    public Rect mapFromParent(Rect aRect){
        Rect sRect = aRect;
        if(parent != null){
            sRect = new Rect(aRect.left - parent.getX(), aRect.top - parent.getY(), aRect.width(), aRect.height());
        }
        
        return sRect;
    }
    
    public Rect mapToScene(Rect aRect){
        Rect sRect = aRect;
        GraphicsItem sItem = this;
        while(sItem.getParent() != null){
            sRect = mapToParent(sRect);
            sItem = sItem.getParent();
        }
        
        return sRect;
    }
    
    public Rect mapFromScene(Rect aRect){
        Rect sRect = aRect;
        GraphicsItem sItem = this;
        while(sItem.getParent() != null){
            sRect = mapFromParent(sRect);
            sItem = sItem.getParent();
        }
        
        return sRect;
    }
    
    
    public ArrayList<GraphicsItem> getChildrenAt(int ax, int ay){
        ArrayList<GraphicsItem> sItems = new ArrayList<GraphicsItem>();
        for(int i = 0; i < children.size(); i++){
            GraphicsItem item = children.get(i);
            if(item.boundingRect.contains(ax, ay)){
                sItems.add(item);
            }
        }
        return sItems;
    }
    
    public GraphicsItem getChildAt(int ax, int ay){
        ArrayList<GraphicsItem> sItems = getChildrenAt(ax, ay);
        if(sItems.size() > 0){
            return sItems.get(0);
        }
        
        return null;
    }
    
    public boolean onTouchEvent(MotionEvent aEvent){
        
        return false;
    }
    
    public void paintEx(Canvas aCanvas){
        if(isVisible){             
            aCanvas.save();
            if(parent != null){
                aCanvas.translate(parent.getX(), parent.getY());
            }
            aCanvas.scale(scaleRatio.x, scaleRatio.y);
            aCanvas.rotate(angle);
            paint(aCanvas);
            if(isFocus){
                paintFocus(aCanvas);
            }
            
            Rect sRect = new Rect(0, 0, getWidth(), getHeight());
            for(int i = 0; i < children.size(); i++){
               GraphicsItem item = children.get(i);
               if(GraphicsUtil.isRectCross(sRect, item.boundingRect())){
                   item.paintEx(aCanvas);
               }
            }
            aCanvas.restore();
        }

    }    
    
    protected void paintFocus(Canvas aCanvas){
        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(3); 
        mPaint.setAlpha(0x77);
        aCanvas.drawRect(boundingRect(), mPaint);  
        mPaint.setAlpha(0xff);
    }
    
    protected abstract void paint(Canvas aCanvas);
}
